home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Mode Examples / Caml-Example.ml < prev    next >
Encoding:
Text File  |  2000-10-30  |  6.9 KB  |  242 lines

  1. *  One hundred lines of Caml *
  2. *  *
  3. *  Contact the author Pierre.Weis@inria.fr *
  4. *  *
  5. *  Created in January 1996. *
  6. *  *
  7. *  Elementary functions *
  8. *   *
  9. *  Using the interactive system, I define the square function, and the *
  10. *  recursive factorial function.  Then I try my new functions with some *
  11. *  examples: *
  12.  
  13. *  >       Caml Light version 0.74 *
  14.  
  15. #let square (x) = x * x;;
  16. square : int -> int = <fun>
  17. #let rec fact (x) =
  18.   if x <= 1 then 1 else x * fact (x - 1);;
  19. fact : int -> int = <fun>
  20. #fact (5);;
  21. - : int = 120
  22. #square (120);;
  23. - : int = 14400
  24.  
  25. *  Automatic memory management *
  26.  
  27. *  All allocation and deallocation operations are fully automatic.  I give the *
  28. *  example of lists. *
  29.  
  30. *  Lists are predefined in Caml, the empty list is [], and the list *
  31. *  constructor is denoted by :: (binary and infix). *
  32.  
  33. #let l = 1 :: 2 :: 3 :: [];;
  34. l : int list = [1; 2; 3]
  35. #[1; 2; 3];;
  36. - : int list = [1; 2; 3]
  37. #5 :: l;;
  38. - : int list = [5; 1; 2; 3]
  39.  
  40. *  Polymorphism: sorting lists *
  41.  
  42. *  Insertion sort is defined with two recursive routines, using pattern matching on lists.  *
  43.  
  44. #let rec sort = function
  45.   | [] -> []
  46.   | x :: l -> insert x (sort l)
  47.  
  48. and insert elem = function
  49.  | [] -> [elem]
  50.  | x :: l -> if elem < x then elem :: x :: l else x :: insert elem l;;
  51. sort : 'a list -> 'a list = <fun>
  52. insert : 'a -> 'a list -> 'a list = <fun>
  53. #sort [2; 1; 0];;
  54. - : int list = [0; 1; 2]
  55. #sort ["yes"; "ok"; "sure"; "ya"; "yep"];;
  56. - : string list = ["ok"; "sure"; "ya"; "yep"; "yes"]
  57.  
  58. *  Imperative features *
  59.  
  60. *  Polynoms being represented as arrays, I add two polynoms by first creating *
  61. *  the resulting polynom, and then filling its slots with two ``for'' loops. *
  62.  
  63. #let add_polynom p1 p2 =
  64.  let result = make_vect (max (vect_length p1) (vect_length p2)) 0 in
  65.  for i = 0 to vect_length p1 - 1 do result.(i) <- p1.(i) done;
  66.  for i = 0 to vect_length p2 - 1 do result.(i) <- result.(i) + p2.(i) done;
  67.  result;;
  68. add_polynom : int vect -> int vect -> unit
  69. #add_polynom [| 1; 2 |] [| 1; 2 |];;
  70. - : int vect = [|2; 4|]
  71.  
  72. *  Accumulators are defined in Caml using updatable cells, named references.  *
  73.  
  74. ref init returns a new cell with initial contents init,
  75. !cell returns the actual contents of cell, and 
  76. cell := val updates cell with the value val. 
  77.  
  78. *  I define fact with an accumulator and a ``for'' loop:  *
  79.  
  80. #let fact n =
  81.  let result = ref 1 in
  82.  for i = 1 to n do
  83.   result := i * !result
  84.  done;
  85.  !result;;
  86. fact : int -> int = <fun>
  87. #fact 5;;
  88. - : int = 120
  89.  
  90. *  Functionality *
  91.  
  92. *  No restrictions on functions, that may be higher-order.  I define the sigma *
  93. *  function that returns the sum of results of applying a given function f to *
  94. *  each element of list: *
  95.  
  96. #let rec sigma f = function
  97.  | [] -> 0
  98.  | x :: l -> f x + sigma f l;;
  99. sigma : ('a -> int) -> 'a list -> int = <fun>
  100.  
  101. *  Temporary functions may be defined as no-name functional values with the *
  102. *  ``function'' construct: *
  103.  
  104. #sigma (function x -> x * x) [1; 2; 3];;
  105. - : int = 14
  106.  
  107. *  Combined with polymorphism, higher-order functionality allows the *
  108. *  definition of the functional composition of two functions. *
  109.  
  110. #let compose f g = function x -> f (g (x));;
  111. compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
  112. #let square_o_fact = compose square fact;;
  113. square_o_fact : int -> int = <fun>
  114. #square_o_fact 5;;
  115. - : int = 14400
  116.  
  117. *  Symbolic computation *
  118.  
  119. *  I consider simple symbolic expressions with integers, variables, let *
  120. *  bindings, and binary operators.  These symbolic expressions are defined as *
  121. *  a new data type, using a type definition: *
  122.  
  123. #type expression =
  124.  | Num of int
  125.  | Var of string
  126.  | Let of string * expression * expression
  127.  | Binop of string * expression * expression;;
  128. Type expression defined.
  129.  
  130. *  Symbolic evaluation of these expressions involves an environment which is *
  131. *  just a list of pairs (identifier, value). *
  132.  
  133. #let rec eval env = function
  134.   | Num i -> i
  135.   | Var x -> assoc x env
  136.   | Let (x, e1, in_e2) ->
  137.      let val_x = eval env e1 in
  138.      eval ((x, val_x) :: env) in_e2
  139.   | Binop (op, e1, e2) ->
  140.      let v1 = eval env e1 in
  141.      let v2 = eval env e2 in
  142.      eval_op op v1 v2
  143.  
  144. and eval_op op v1 v2 =
  145.  match op with
  146.  | "+" -> v1 + v2
  147.  | "-" -> v1 - v2
  148.  | "*" -> v1 * v2
  149.  | "/" -> v1 / v2
  150.  | _ -> failwith ("Unknown operator: " ^ op);;
  151. eval : (string * int) list -> expression -> int = <fun>
  152. eval_op : string -> int -> int -> int = <fun>
  153.  
  154. *  As an example, we evaluate the phrase ``let x = 1 in x + x'':  *
  155.  
  156. #eval [] (Let ("x", Num 1, Binop ("+", Var "x", Var "x")));;
  157. - : int = 2
  158.  
  159. *  In addition to data type definition, the pattern matching facility leads to *
  160. *  an easy way of defining functions on symbolic data.  For instance, from the *
  161. *  type definition of expressions: *
  162.  
  163. type expression =
  164.  | Num of int
  165.  | Var of string
  166.  | Let of string * expression * expression
  167.  | Binop of string * expression * expression
  168.  
  169. *  we get the skeleton of the printing procedure for expression:  *
  170.  
  171. let print_expression = function
  172.  | Num int ->
  173.  | Var string ->
  174.  | Let (string, expression1, expression2) ->
  175.  | Binop (string, expression1, expression2) ->
  176.  
  177. *  We just have to complete the pattern matching clauses to get the printing *
  178. *  routine: *
  179.  
  180. #let rec print_expression = function
  181.  | Num int -> print_int int
  182.  | Var string -> print_string string
  183.  | Let (string, expression1, expression2) ->
  184.     print_string "let "; print_string string; print_string " = ";
  185.     print_expression expression1; print_string " in ";
  186.     print_expression expression2
  187.  | Binop (string, expression1, expression2) ->
  188.     print_string "("; print_expression expression1;
  189.     print_string (" "^string^" ");
  190.     print_expression expression2; print_string ")";;
  191. print_expression : expression -> unit = <fun>
  192. #print_expression (Let ("x", Num 1, Binop ("+", Var "x", Var "x")));;
  193. let x = 1 in (x + x)- : unit = ()
  194.  
  195. *  Parsing data *
  196.  
  197. *  Caml offers a rich panel of parsing tools: it includes traditional lex and *
  198. *  yacc interfaces, but also an original stream primitive data type, with its *
  199. *  associated ``functional parsing'' technology. *
  200.  
  201. *  Writing a parser is always a bit technical, you may like to omit it.  *
  202. *  However, you can find a parser for the above expression data type. *
  203.  
  204. *  Elementary debugging *
  205.  
  206. *  Just for completeness, let me show you the simplest way to debug programs, *
  207. *  using the trace facility: *
  208.  
  209. #let rec fib x = if x <= 1 then 1 else fib (x - 1) + fib (x - 2);;
  210. fib : int -> int = <fun>
  211. #trace "fib";;
  212.  
  213. *  The function fib is now traced. *
  214.  
  215. - : unit = ()
  216. #fib 3;;
  217. fib <-- 3
  218. fib <-- 1
  219. fib --> 1
  220. fib <-- 2
  221. fib <-- 0
  222. fib --> 1
  223. fib <-- 1
  224. fib --> 1
  225. fib --> 2
  226. fib --> 3
  227. - : int = 3
  228.  
  229. *  More *
  230.  
  231. *  If you know the lambda calculus, click here to see a more significative *
  232. *  example of symbolic data manipulation using Caml: the definition of *
  233. *  lambda-terms with their associated lexical analyzer, parser and printer, *
  234. *  within about fifty lines of Caml code. *
  235.  
  236.  
  237. *  Caml home page Last modified: Friday, March 27, 1998  *
  238. *  Copyright © 1995, 1996, 1997, 1998, 1999, 2000 INRIA all rights reserved.  *
  239.  
  240. *  Contact the author Pierre.Weis@inria.fr *
  241.  
  242.